#pragma once

#include "OpaqueExpression.h"

#include "Behavior.h"
#include "Parameter.h"

namespace uml {

OpaqueExpression::OpaqueExpression(const QString& umlType)
    : ValueSpecification(umlType) {}

void OpaqueExpression::fromJson(const QJsonObject& json, QStringList& errorList) {
    if (json.isEmpty()) {
        return;
    }

    ValueSpecification::fromJson(json, errorList);
    behavior_ = JsonSerializable::create<Behavior>(json.value("behavior"), errorList);

    JsonSerializable::fromJsonArray(bodys_, "bodys", json, errorList);
    JsonSerializable::fromJsonArray(languages_, "languages", json, errorList);
    result_ = JsonSerializable::create<Parameter>(json.value("result"), errorList);

}

void OpaqueExpression::toJson(QJsonObject& json) {
    ValueSpecification::toJson(json);
    if (behavior_) {
        QJsonObject behavior_json;
        behavior_->toJson(behavior_json);
        json.insert("behavior", behavior_json);
    }
    JsonSerializable::toJsonArray(bodys_, "bodys", json);
    JsonSerializable::toJsonArray(languages_, "languages", json);
    if (result_) {
        QJsonObject result_json;
        result_->toJson(result_json);
        json.insert("result", result_json);
    }
}

/// <summary>
/// isIntegral
    /// The query isIntegral() tells whether an expression is intended to produce an
    /// Integer.
/// </summary>
    /// <code>
    /// result = (false)
    /// </code>
bool OpaqueExpression::isIntegral() const
{
    return false;
}

/// <summary>
/// isNonNegative
    /// The query isNonNegative() tells whether an integer expression has a non-negative
    /// value.
/// </summary>
    /// <code>
    /// self.isIntegral()
    /// </code>
    /// <code>
    /// result = (false)
    /// </code>
bool OpaqueExpression::isNonNegative() const
{
    return false;
}

/// <summary>
/// isPositive
    /// The query isPositive() tells whether an integer expression has a positive value.
/// </summary>
    /// <code>
    /// result = (false)
    /// </code>
    /// <code>
    /// self.isIntegral()
    /// </code>
bool OpaqueExpression::isPositive() const
{
    return false;
}

/// <summary>
/// value
    /// The query value() gives an integer value for an expression intended to produce
    /// one.
/// </summary>
    /// <code>
    /// self.isIntegral()
    /// </code>
    /// <code>
    /// result = (0)
    /// </code>
int OpaqueExpression::value() const
{
    return 0;
}

/// <summary>
/// behavior getter
/// Specifies the behavior of the OpaqueExpression as a UML Behavior.
/// </summary>
shared_ptr<Behavior> OpaqueExpression::behavior() const {
    return behavior_;
}

/// <summary>
/// behavior setter
/// Specifies the behavior of the OpaqueExpression as a UML Behavior.
/// </summary>
void OpaqueExpression::setBehavior(shared_ptr<Behavior> value) {
    behavior_ = value;
}

/// <summary>
/// bodys getter
/// A textual definition of the behavior of the OpaqueExpression, possibly in
/// multiple languages.
/// </summary>
vector<QString>& OpaqueExpression::bodys() {
    return bodys_;
}

/// <summary>
/// languages getter
/// Specifies the languages used to express the textual bodies of the
/// OpaqueExpression.  Languages are matched to body Strings by order. The
/// interpretation of the body depends on the languages. If the languages are
/// unspecified, they may be implicit from the expression body or the context.
/// </summary>
vector<QString>& OpaqueExpression::languages() {
    return languages_;
}

/// <summary>
/// result getter
/// If an OpaqueExpression is specified using a UML Behavior, then this refers to
/// the single required return Parameter of that Behavior. When the Behavior
/// completes execution, the values on this Parameter give the result of evaluating
/// the OpaqueExpression.
/// </summary>
shared_ptr<Parameter> OpaqueExpression::result() const {
    return result_;
}

/// <summary>
/// result setter
/// If an OpaqueExpression is specified using a UML Behavior, then this refers to
/// the single required return Parameter of that Behavior. When the Behavior
/// completes execution, the values on this Parameter give the result of evaluating
/// the OpaqueExpression.
/// </summary>
void OpaqueExpression::setResult(shared_ptr<Parameter> value) {
    result_ = value;
}

} // namespace uml
